JNI使用过程记录,Java调用C++函数,JNI层使用和实例化Java对象 您所在的位置:网站首页 object 函数 JNI使用过程记录,Java调用C++函数,JNI层使用和实例化Java对象

JNI使用过程记录,Java调用C++函数,JNI层使用和实例化Java对象

2023-05-02 23:53| 来源: 网络整理| 查看: 265

近期提供给JAVA应用使用的编解码协议库,需求就是编码的字符串,需要解码为Java对象;回应消息的Java对象,需要编码为指定格式的字符串,把模板代码总结下,主要涉及几个点:

1、在JNI层找到Java对象,及其属性变量的值,然后转换为JNI层的内存数据;

2、在JNI层实例化Java对象,并设置这个Java对象的属性变量,并返回这个Java对象;

示例代码如下:

Java对象 

public class TestKey  {     public String name;     public String desc;     public int usage;     public String keySpec;     public String expire;     public String source;       public String credential_username;     public String credential_password; }

JNI层实例化TestKey:

static jobject get_jobject(JNIEnv *env, const char *object_name){     if (env == NULL || object_name == NULL){         return NULL;     }     jclass clazz = NULL;     jobject jobj = NULL;     jmethodID mid_construct = NULL;       //1. 获取Person类的Class引用     clazz = env->FindClass(object_name);     if(clazz == NULL){         LOGD("clazz null");         return NULL;     }     //2. 获取类的默认构造函数ID     mid_construct = env->GetMethodID(clazz, "", "()V");     if(mid_construct == NULL){         LOGD("construct null");         return NULL;     }     //3.实例化这个对象     jobj = env->NewObject(clazz, mid_construct);     if(jobj == NULL){         LOGD("jobject null");         return NULL;     }     return jobj; }  JNIEXPORT jobject JNICALL Java_com_xxx_kmip_ProtocolUtil_decodeTestKeyRequestMessage   (JNIEnv *env, jclass obj, jbyteArray j_input){       jclass clazz = NULL;     jobject jobj = NULL;     jfieldID fid_name = NULL;     jfieldID fid_desc = NULL;     jfieldID fid_usage = NULL;     jfieldID fid_keySpec = NULL;     jfieldID fid_expire = NULL;     jfieldID fid_source = NULL;     jfieldID fid_credential_name = NULL;      jfieldID fid_credential_passwd = NULL;     env->GetJavaVM(&javaVM);     char* decode_str = (char*)env->GetByteArrayElements(j_input, 0);     int  length = env->GetArrayLength(j_input);     char name[32] = {'\0'};     char description[255]= {'\0'};     char cryptographic_algorithm[128]= {'\0'};     int  cryptographic_algorithm_length = 0;     int  cryptographic_usage_mask = 0;     char source[128]= {'\0'};             //中间省略赋值过程     //1. 找到请求Class的引用     clazz = env->FindClass("com/test/api/entity/TestKey");     if(clazz == NULL){         LOGD("clazz null");         return NULL;     }     //2. 获取实例方法ID和变量ID     fid_name = env->GetFieldID(clazz, "name", "Ljava/lang/String;");     fid_keySpec = env->GetFieldID(clazz, "keySpec", "Ljava/lang/String;");      fid_desc = env->GetFieldID(clazz, "desc", "Ljava/lang/String;");     fid_expire = env->GetFieldID(clazz, "expire", "Ljava/lang/String;");     fid_source = env->GetFieldID(clazz, "source", "Ljava/lang/String;");     fid_usage = env->GetFieldID(clazz, "usage", "I");     fid_credential_name = env->GetFieldID(clazz, "credential_username", "Ljava/lang/String;");     fid_credential_passwd = env->GetFieldID(clazz, "credential_password", "Ljava/lang/String;");     if(fid_name==NULL          || fid_keySpec==NULL          || fid_desc==NULL           || fid_source==NULL          || fid_usage==NULL){         LOGD("age|name null");         return NULL;     }     //获取输出对象     jobj = get_jobject(env, "com/test/api/entity/TestKey");     if (jobj == NULL){         return NULL;     }                       //赋值     env->SetIntField(jobj, fid_usage, 2);     jstring j_name = env->NewStringUTF(name);     env->SetObjectField(jobj, fid_name, j_name);     jstring j_desc= env->NewStringUTF(description);     env->SetObjectField(jobj, fid_desc, j_desc);     jstring j_spec = env->NewStringUTF(cryptographic_algorithm);     env->SetObjectField(jobj, fid_keySpec, j_spec);     //释放内存     env->ReleaseByteArrayElements(j_input, (jbyte*)decode_str, JNI_ABORT);       kmip_free_request_message(&ctx, &req_msg_client);     return jobj; }

Java对象,输入到JNI层使用

public class CommonResponseMessage{ public int    return_code; public int    result_reason; public String error_message;   public String uniq_id; }

JNI层使用Java对象

//输入java对象,输出byte[]数组 JNIEXPORT jbyteArray JNICALL Java_com_xxx_ProtocolUtil_encodeTestKeyResponseMessage   (JNIEnv *env, jclass obj, jobject j_input, jint op_code){     if (j_input == NULL){         return NULL;     }     jclass clazz = NULL;      jfieldID fid_return_code = NULL;     jfieldID fid_uniq_id = NULL;      jfieldID fid_error_message = NULL;      jfieldID fid_result_reason = NULL;      env->GetJavaVM(&javaVM);            //1. 获取Class引用     clazz = env->FindClass("com/test/api/entity/CommonResponseMessage");     if(clazz == NULL){         LOGD("clazz null");         return NULL;     }     //2. 获取实例方法ID和变量ID     fid_uniq_id = env->GetFieldID(clazz, "uniq_id", "Ljava/lang/String;");     fid_error_message = env->GetFieldID(clazz, "error_message", "Ljava/lang/String;");     fid_return_code = env->GetFieldID(clazz, "return_code", "I");     fid_result_reason = env->GetFieldID(clazz, "result_reason", "I");     if(fid_uniq_id == NULL || fid_return_code==NULL || fid_error_message==NULL || fid_result_reason == NULL){         LOGD("age|name null");         return NULL;     }       //3.得到对象值     jint return_code = env->GetIntField(j_input, fid_return_code);     printf("return_code:%d\r\n", (int)return_code);     if (return_code != 0){         //failed.         resp_bi.result_status = KMIP_STATUS_OPERATION_FAILED;         jstring j_fid_error_message = (jstring)env->GetObjectField(j_input, fid_error_message);         const char* cstr= env->GetStringUTFChars(j_fid_error_message, NULL);         //保存cstr         env->ReleaseStringUTFChars(j_fid_error_message, cstr);          //fid_result_reason         jint result_reason = env->GetIntField(j_input, fid_result_reason);      }else{           jstring j_fid_uniq_id = (jstring)env->GetObjectField(j_input, fid_uniq_id);         const char* cstr= env->GetStringUTFChars(j_fid_uniq_id, NULL);          //保存cstr         env->ReleaseStringUTFChars(j_fid_uniq_id, cstr);      }     //….省略编码处理     return result;   }

Java 基本类型与方法签名中参数类型和返回值类型的映射关系如下:

内存使用,关于局部引用和全局引用,讲的还是蛮清晰的:http://www.itpub.net/2020/01/02/4987/

Native层返回的jobject对象和引用是否需要在native层销毁,这篇文章有说:jni中的NewStringUTF这个函数调用后需要释放内存吗?



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有